package io.chenglicun.modules.check.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.chenglicun.common.entity.BaseEntity;
import io.chenglicun.common.page.PageData;
import io.chenglicun.common.service.impl.CrudServiceImpl;
import io.chenglicun.common.utils.ConvertUtils;
import io.chenglicun.common.utils.DateUtils;
import io.chenglicun.modules.check.dao.ClcCheckDetailDao;
import io.chenglicun.modules.check.dao.ClcFileManageDao;
import io.chenglicun.modules.check.dto.ClcCheckDetailDTO;
import io.chenglicun.modules.check.dto.ClcFileManageDTO;
import io.chenglicun.modules.check.entity.ClcCheckDetailEntity;
import io.chenglicun.modules.check.entity.ClcFileManageEntity;
import io.chenglicun.modules.check.service.ClcCheckDetailService;
import io.chenglicun.modules.check.service.ClcFileManageService;
import io.chenglicun.modules.evaluation.dao.ClcEvaluationTemplateDao;
import io.chenglicun.modules.evaluation.dao.ClcTemplateTypeDao;
import io.chenglicun.modules.evaluation.dao.ClcTypeStandardDao;
import io.chenglicun.modules.evaluation.entity.ClcEvaluationTemplateEntity;
import io.chenglicun.modules.evaluation.entity.ClcTemplateTypeEntity;
import io.chenglicun.modules.evaluation.entity.ClcTypeStandardEntity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 考核明细
 *
 * @author HB 137664951@qq.com
 * @since 1.0 2023-11-29
 */
@Service
public class ClcCheckDetailServiceImpl extends CrudServiceImpl<ClcCheckDetailDao, ClcCheckDetailEntity, ClcCheckDetailDTO> implements ClcCheckDetailService {

    @Autowired
    private ClcFileManageService fileManageService;
    @Autowired
    private ClcEvaluationTemplateDao templateDao;
    @Autowired
    private ClcTemplateTypeDao typeDao;
    @Autowired
    private ClcTypeStandardDao standardDao;

    @Override
    public QueryWrapper<ClcCheckDetailEntity> getWrapper(Map<String, Object> params){
        QueryWrapper<ClcCheckDetailEntity> wrapper = new QueryWrapper<>();

        Object checkId = params.get("checkId");
        Object scoreType = params.get("scoreType");
        Object status = params.get("status");
        wrapper.eq(ObjectUtil.isNotEmpty(checkId), "check_id", checkId);
        if (scoreType != null) {
            int i = Integer.parseInt(scoreType.toString());
            if (i == 0) wrapper.lt("score", 0);
            if (i == 1) wrapper.gt("score", 0);
        }
        wrapper.eq(ObjectUtil.isNotEmpty(status), "status", status);

        return wrapper;
    }

    @Override
    public PageData<ClcCheckDetailDTO> page(Map<String, Object> params) {
        PageData<ClcCheckDetailDTO> page = super.page(params);

        this.setData(page.getList().toArray(new ClcCheckDetailDTO[0]));

        return page;
    }

    @Override
    public List<ClcCheckDetailDTO> getByCheckIds(Long... checkIds) {
        List<ClcCheckDetailEntity> entities = baseDao.selectList(
                new QueryWrapper<ClcCheckDetailEntity>().lambda().in(ClcCheckDetailEntity::getCheckId, Arrays.asList(checkIds)));

        List<ClcCheckDetailDTO> dtos = ConvertUtils.sourceToTarget(entities, ClcCheckDetailDTO.class);

        this.setData(dtos.toArray(new ClcCheckDetailDTO[0]));

        return dtos;
    }

    private void setData(ClcCheckDetailDTO... dtos) {
        if (dtos == null || dtos.length == 0) return;

        Long[] ids = Arrays.stream(dtos).filter(Objects::nonNull).map(ClcCheckDetailDTO::getId).toArray(Long[]::new);
        List<ClcFileManageDTO> fileManageList = fileManageService.getList(ids);

        List<Long> standardIds = Arrays.stream(dtos).filter(Objects::nonNull).map(ClcCheckDetailDTO::getStandardId).collect(Collectors.toList());
        List<ClcTypeStandardEntity> standardEntities = standardDao.selectList(new QueryWrapper<ClcTypeStandardEntity>().lambda().in(BaseEntity::getId, standardIds));

        List<Long> typeIds = Arrays.stream(dtos).filter(Objects::nonNull).map(ClcCheckDetailDTO::getTypeId).collect(Collectors.toList());
        List<ClcTemplateTypeEntity> typeEntities = typeDao.selectList(new QueryWrapper<ClcTemplateTypeEntity>().lambda().in(BaseEntity::getId, typeIds));
        for (ClcCheckDetailDTO dto : dtos) {
            dto.setCheckUrls(
                    fileManageList.stream().filter(t -> t.getSourceId().equals(dto.getId()) && t.getSourceType().equals(0))
                            .map(ClcFileManageDTO::getFileUrl).collect(Collectors.toList())
            );
            dto.setRectificationUrls(
                    fileManageList.stream().filter(t -> t.getSourceId().equals(dto.getId()) && t.getSourceType().equals(1))
                            .map(ClcFileManageDTO::getFileUrl).collect(Collectors.toList())
            );
            dto.setStandardDescribe(
                    standardEntities.stream().filter(t -> t.getId().equals(dto.getStandardId()))
                            .map(ClcTypeStandardEntity::getStandardDescribe).findFirst().orElse(null)
            );
            dto.setTypeName(
                    typeEntities.stream().filter(t -> t.getId().equals(dto.getTypeId()))
                            .map(ClcTemplateTypeEntity::getName).findFirst().orElse(null)
            );
        }
    }

    @Override
    @Transactional
    public boolean rectification(ClcCheckDetailDTO dto) {
        ClcCheckDetailDTO detailDTO = super.get(dto.getId());

        ClcTemplateTypeEntity typeEntity = typeDao.selectById(detailDTO.getTypeId());
        ClcEvaluationTemplateEntity templateEntity = templateDao.selectById(typeEntity.getTemplateId());
        Date date = DateUtils.addDateHours(detailDTO.getCreateDate(), templateEntity.getScopeTime());
        if (date.compareTo(new Date()) < 0) {
            return false;
        }

        fileManageService.deleteBySourceIds(1, dto.getId());

        List<String> rectificationUrls = dto.getRectificationUrls();
        for (String rectificationUrl : rectificationUrls) {
            ClcFileManageDTO fileManage = new ClcFileManageDTO();
            fileManage.setSourceId(dto.getId());
            fileManage.setSourceType(1);
            fileManage.setFileUrl(rectificationUrl);
            fileManageService.save(fileManage);
        }
        detailDTO.setStatus(1);
        super.update(detailDTO);
        return true;
    }


    @Override
    @Transactional
    public void deleteByCheckIds(Long... checkIds) {
        List<ClcCheckDetailDTO> dtos = this.getByCheckIds(checkIds);
        Long[] ids = dtos.stream().map(ClcCheckDetailDTO::getId).toArray(Long[]::new);
        fileManageService.deleteBySourceIds(null, ids);
        baseDao.deleteBatchIds(Arrays.asList(ids));
    }

    @Override
    @Transactional
    public void saveBatch(List<ClcCheckDetailDTO> dtos) {
        List<Long> typeIds = dtos.stream().map(ClcCheckDetailDTO::getTypeId).filter(Objects::nonNull).collect(Collectors.toList());
        List<ClcTemplateTypeEntity> typeEntities = typeDao.selectList(new QueryWrapper<ClcTemplateTypeEntity>().lambda().in(BaseEntity::getId, typeIds));
        List<Long> standardIds = dtos.stream().map(ClcCheckDetailDTO::getStandardId).filter(Objects::nonNull).collect(Collectors.toList());
        List<ClcTypeStandardEntity> standardEntities = standardDao.selectList(new QueryWrapper<ClcTypeStandardEntity>().lambda().in(BaseEntity::getId, standardIds));

        for (ClcCheckDetailDTO dto : dtos) {
            // 考核图片
            List<String> checkUrls = dto.getCheckUrls();
            // 考核类型
            ClcTemplateTypeEntity typeEntity = typeEntities.stream().filter(t -> t.getId().equals(dto.getTypeId())).findFirst().orElse(null);
            // 考核标准
            ClcTypeStandardEntity standardEntity = standardEntities.stream().filter(t -> t.getId().equals(dto.getStandardId())).findFirst().orElse(null);
            // 计算分数
            dto.setScore(calculateScore(typeEntity, standardEntity, checkUrls.size()));
            // 保存考核明细
            this.save(dto);
            // 保存图片
            for (String checkUrl : checkUrls) {
                ClcFileManageDTO fileManage = new ClcFileManageDTO();
                fileManage.setSourceId(dto.getId());
                fileManage.setSourceType(0);
                fileManage.setFileUrl(checkUrl);
                fileManageService.save(fileManage);
            }
        }
    }

    private int calculateScore(ClcTemplateTypeEntity typeEntity, ClcTypeStandardEntity standardEntity, Integer count) {
        int result = 0;

        if (typeEntity == null || standardEntity == null) return result;
        // 得分类型(0:非加分 1:加分)
        int scoreType = typeEntity.getScoreType();
        // 扣分上限
        int upScore = Math.abs(standardEntity.getScoreTotal());
        // 分数
        int subScore = Math.abs(standardEntity.getScore());
        // 计分规则 ( =_1_-2| =_2_-5|>=_3_-15 )
        String scoreRule = standardEntity.getScoreRule();
        // 是否计数
        int isCount = standardEntity.getIsCount();


        if (isCount == 0) { // 不计数
            result = subScore;
        } else { // 计数
            if (StringUtils.isEmpty(scoreRule)) { // 计分规则为空
                result = Math.min(subScore * count, upScore);
            } else {
                String[] scoreRuleArr = scoreRule.split("\\|");
                for (String s : scoreRuleArr) {
                    String[] scoreRuleSub = s.split("_");
                    if("=".equals(scoreRuleSub[0]) && count == Integer.parseInt(scoreRuleSub[1])) {
                        result = Math.abs(Integer.parseInt(scoreRuleSub[2]));
                        break;
                    }
                    if(">=".equals(scoreRuleSub[0]) && count >= Integer.parseInt(scoreRuleSub[1])) {
                        result = Math.abs(Integer.parseInt(scoreRuleSub[2]));
                        break;
                    }
                }
            }
        }

        return scoreType == 0 ? -result : result;
    }
}